/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.seari.line17.handler;

import com.seari.bean.Line17.Line17DataBean;
import com.seari.bean.Line17.Line17Instruct;
import com.seari.line17.Line17Helper;
import com.seari.utils.DataUtil;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.util.List;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author Rainbow
 */
public class Line17Decoder extends ByteToMessageDecoder
{
    protected static Logger logger = LoggerFactory.getLogger(Line17Decoder.class);
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception
    {
        if(in.readableBytes() < Line17Helper.FRAME_LENGTH_WITHOUT_CONTENT)
        {
            //小于最小帧长直接返回
            return;
        }
        in.markReaderIndex();
        if(in.readByte() != (byte)0xEB || in.readByte() != (byte)0x90 )
        {
            //未读到正确的HEAD直接返回
            return;
        }
        byte[] packageInfo = new byte[5];
        in.readBytes(packageInfo);
        int totalLength = DataUtil.getHighLowByteValue(packageInfo[4], packageInfo[3]);
        totalLength = totalLength + 2; //加上2字节校验位长度
        if(in.readableBytes() < totalLength)
        {
            //包长不够时重置读指针等待下次包数据
            in.resetReaderIndex();
            return;
        }
        
        
        
        
        byte[] content = new byte[totalLength];
        in.readBytes(content);
        byte[] headInfo = ArrayUtils.addAll(Line17Helper.LINE17_HEADER, packageInfo);
        byte[] result = ArrayUtils.addAll(headInfo, content);
        Line17DataBean dataBean = decode(result);
        if(null == dataBean || (dataBean.equals("")))
        	
        {
            logger.warn("parse frame failed");
        }
        else{
            out.add(dataBean);
        }
        
        logger.info(DataUtil.BytesToHexStr(result));
    }
    
    public Line17DataBean decode(byte[] bytes)
    {
        Line17DataBean dataBean = null;
        if(bytes[0] == (byte)0xEB && bytes[1] == (byte)0x90)
        {
            Line17Instruct instruct = new Line17Instruct();
            dataBean = new Line17DataBean();
            instruct.sysID = bytes[2];
            instruct.packageNoLow = bytes[3];
            instruct.packageNoHigh = bytes[4];
            instruct.totalLenLow = bytes[5];
            instruct.totalLenHigh = bytes[6];
            instruct.multiFlag = bytes[7];
            instruct.msgID = bytes[8];
            instruct.msgCountLow = bytes[9];
            instruct.msgCountMid = bytes[10];
            instruct.msgCountHigh = bytes[11];
            instruct.startAddressLow = bytes[12];
            instruct.startAddressMid = bytes[13];
            instruct.startAddressHigh = bytes[14];
            instruct.content = DataUtil.subBytes(bytes, 15, bytes.length - 17);
            instruct.chkLow = bytes[bytes.length - 2];
            instruct.chkHigh = bytes[bytes.length - 1];
            
            dataBean.setSysID((instruct.sysID & 0xff) + "");
            dataBean.setMsgID(instruct.msgID & 0xff);
            dataBean.setPackageNo(instruct.getPackageNoInt());
            dataBean.setStartAddress(instruct.getStartAddressCountInt());
            dataBean.setContent(instruct.content);
        }else{
            logger.warn("frame illegal");
        }
        return dataBean;
    }
    
}
